/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
 *
 * The information contained herein is property of Nordic Semiconductor ASA.
 * Terms and conditions of usage are described in detail in NORDIC
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 *
 * Licensees are granted free, non-transferable use of the information. NO
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 * the file.
 */

/** @file
 *
 * @defgroup ble_sdk_srv_gls Glucose Service
 * @{
 * @ingroup ble_sdk_srv
 * @brief Glucose Service module.
 *
 * @details This module implements the Glucose Service.
 *
 * @note The application must propagate BLE stack events to the Glucose Service module by calling
 *       ble_gls_on_ble_evt() from the @ref softdevice_handler callback.
 *
 * @note Attention!
 *  To maintain compliance with Nordic Semiconductor ASA Bluetooth profile
 *  qualification listings, this section of source code must not be modified.
 */

#ifndef BLE_GLS_H__
#define BLE_GLS_H__

#include <stdint.h>
#include <stdbool.h>
#include "ble.h"
#include "ble_srv_common.h"
#include "ble_date_time.h"

/**@brief Glucose feature */
#define BLE_GLS_FEATURE_LOW_BATT 0x0001      /**< Low Battery Detection During Measurement Supported */
#define BLE_GLS_FEATURE_MALFUNC 0x0002       /**< Sensor Malfunction Detection Supported */
#define BLE_GLS_FEATURE_SAMPLE_SIZE 0x0004   /**< Sensor Sample Size Supported */
#define BLE_GLS_FEATURE_INSERT_ERR 0x0008    /**< Sensor Strip Insertion Error Detection Supported */
#define BLE_GLS_FEATURE_TYPE_ERR 0x0010      /**< Sensor Strip Type Error Detection Supported */
#define BLE_GLS_FEATURE_RES_HIGH_LOW 0x0020  /**< Sensor Result High-Low Detection Supported */
#define BLE_GLS_FEATURE_TEMP_HIGH_LOW 0x0040 /**< Sensor Temperature High-Low Detection Supported */
#define BLE_GLS_FEATURE_READ_INT 0x0080      /**< Sensor Read Interrupt Detection Supported */
#define BLE_GLS_FEATURE_GENERAL_FAULT 0x0100 /**< General Device Fault Supported */
#define BLE_GLS_FEATURE_TIME_FAULT 0x0200    /**< Time Fault Supported */
#define BLE_GLS_FEATURE_MULTI_BOND 0x0400    /**< Multiple Bond Supported */

/**@brief Glucose measurement flags */
#define BLE_GLS_MEAS_FLAG_TIME_OFFSET 0x01   /**< Time Offset Present */
#define BLE_GLS_MEAS_FLAG_CONC_TYPE_LOC 0x02 /**< Glucose Concentration, Type, and Sample Location Present */
#define BLE_GLS_MEAS_FLAG_UNITS_KG_L 0x00    /**< Glucose Concentration Units kg/L */
#define BLE_GLS_MEAS_FLAG_UNITS_MOL_L 0x04   /**< Glucose Concentration Units mol/L */
#define BLE_GLS_MEAS_FLAG_SENSOR_STATUS 0x08 /**< Sensor Status Annunciation Present */
#define BLE_GLS_MEAS_FLAG_CONTEXT_INFO 0x10  /**< Context Information Follows */

/**@brief Glucose measurement type */
#define BLE_GLS_MEAS_TYPE_CAP_BLOOD 1    /**< Capillary whole blood */
#define BLE_GLS_MEAS_TYPE_CAP_PLASMA 2   /**< Capillary plasma */
#define BLE_GLS_MEAS_TYPE_VEN_BLOOD 3    /**< Venous whole blood */
#define BLE_GLS_MEAS_TYPE_VEN_PLASMA 4   /**< Venous plasma */
#define BLE_GLS_MEAS_TYPE_ART_BLOOD 5    /**< Arterial whole blood */
#define BLE_GLS_MEAS_TYPE_ART_PLASMA 6   /**< Arterial plasma */
#define BLE_GLS_MEAS_TYPE_UNDET_BLOOD 7  /**< Undetermined whole blood */
#define BLE_GLS_MEAS_TYPE_UNDET_PLASMA 8 /**< Undetermined plasma */
#define BLE_GLS_MEAS_TYPE_FLUID 9        /**< Interstitial fluid (ISF) */
#define BLE_GLS_MEAS_TYPE_CONTROL 10     /**< Control solution */

/**@brief Glucose measurement location */
#define BLE_GLS_MEAS_LOC_FINGER 1     /**< Finger */
#define BLE_GLS_MEAS_LOC_AST 2        /**< Alternate Site Test (AST) */
#define BLE_GLS_MEAS_LOC_EAR 3        /**< Earlobe */
#define BLE_GLS_MEAS_LOC_CONTROL 4    /**< Control solution */
#define BLE_GLS_MEAS_LOC_NOT_AVAIL 15 /**< Sample Location value not available */

/**@brief Glucose sensor status annunciation */
#define BLE_GLS_MEAS_STATUS_BATT_LOW 0x0001      /**< Device battery low at time of measurement */
#define BLE_GLS_MEAS_STATUS_SENSOR_FAULT 0x0002  /**< Sensor malfunction or faulting at time of measurement */
#define BLE_GLS_MEAS_STATUS_SAMPLE_SIZE 0x0004   /**< Sample size for blood or control solution insufficient at time of measurement */
#define BLE_GLS_MEAS_STATUS_STRIP_INSERT 0x0008  /**< Strip insertion error */
#define BLE_GLS_MEAS_STATUS_STRIP_TYPE 0x0010    /**< Strip type incorrect for device */
#define BLE_GLS_MEAS_STATUS_RESULT_HIGH 0x0020   /**< Sensor result higher than the device can process */
#define BLE_GLS_MEAS_STATUS_RESULT_LOW 0x0040    /**< Sensor result lower than the device can process */
#define BLE_GLS_MEAS_STATUS_TEMP_HIGH 0x0080     /**< Sensor temperature too high for valid test/result at time of measurement */
#define BLE_GLS_MEAS_STATUS_TEMP_LOW 0x0100      /**< Sensor temperature too low for valid test/result at time of measurement */
#define BLE_GLS_MEAS_STATUS_STRIP_PULL 0x0200    /**< Sensor read interrupted because strip was pulled too soon at time of measurement */
#define BLE_GLS_MEAS_STATUS_GENERAL_FAULT 0x0400 /**< General device fault has occurred in the sensor */
#define BLE_GLS_MEAS_STATUS_TIME_FAULT 0x0800    /**< Time fault has occurred in the sensor and time may be inaccurate */

/**@brief Glucose measurement context flags */
#define BLE_GLS_CONTEXT_FLAG_CARB 0x01     /**< Carbohydrate id and carbohydrate present */
#define BLE_GLS_CONTEXT_FLAG_MEAL 0x02     /**< Meal present */
#define BLE_GLS_CONTEXT_FLAG_TESTER 0x04   /**< Tester-health present */
#define BLE_GLS_CONTEXT_FLAG_EXERCISE 0x08 /**< Exercise duration and exercise intensity present */
#define BLE_GLS_CONTEXT_FLAG_MED 0x10      /**< Medication ID and medication present */
#define BLE_GLS_CONTEXT_FLAG_MED_KG 0x00   /**< Medication value units, kilograms */
#define BLE_GLS_CONTEXT_FLAG_MED_L 0x20    /**< Medication value units, liters */
#define BLE_GLS_CONTEXT_FLAG_HBA1C 0x40    /**< Hba1c present */
#define BLE_GLS_CONTEXT_FLAG_EXT 0x80      /**< Extended flags present */

/**@brief Glucose measurement context carbohydrate ID */
#define BLE_GLS_CONTEXT_CARB_BREAKFAST 1 /**< Breakfast */
#define BLE_GLS_CONTEXT_CARB_LUNCH 2     /**< Lunch */
#define BLE_GLS_CONTEXT_CARB_DINNER 3    /**< Dinner */
#define BLE_GLS_CONTEXT_CARB_SNACK 4     /**< Snack */
#define BLE_GLS_CONTEXT_CARB_DRINK 5     /**< Drink */
#define BLE_GLS_CONTEXT_CARB_SUPPER 6    /**< Supper */
#define BLE_GLS_CONTEXT_CARB_BRUNCH 7    /**< Brunch */

/**@brief Glucose measurement context meal */
#define BLE_GLS_CONTEXT_MEAL_PREPRANDIAL 1  /**< Preprandial (before meal) */
#define BLE_GLS_CONTEXT_MEAL_POSTPRANDIAL 2 /**< Postprandial (after meal) */
#define BLE_GLS_CONTEXT_MEAL_FASTING 3      /**< Fasting */
#define BLE_GLS_CONTEXT_MEAL_CASUAL 4       /**< Casual (snacks, drinks, etc.) */
#define BLE_GLS_CONTEXT_MEAL_BEDTIME 5      /**< Bedtime */

/**@brief Glucose measurement context tester */
#define BLE_GLS_CONTEXT_TESTER_SELF 1       /**< Self */
#define BLE_GLS_CONTEXT_TESTER_PRO 2        /**< Health care professional */
#define BLE_GLS_CONTEXT_TESTER_LAB 3        /**< Lab test */
#define BLE_GLS_CONTEXT_TESTER_NOT_AVAIL 15 /**< Tester value not available */

/**@brief Glucose measurement context health */
#define BLE_GLS_CONTEXT_HEALTH_MINOR 1      /**< Minor health issues */
#define BLE_GLS_CONTEXT_HEALTH_MAJOR 2      /**< Major health issues */
#define BLE_GLS_CONTEXT_HEALTH_MENSES 3     /**< During menses */
#define BLE_GLS_CONTEXT_HEALTH_STRESS 4     /**< Under stress */
#define BLE_GLS_CONTEXT_HEALTH_NONE 5       /**< No health issues */
#define BLE_GLS_CONTEXT_HEALTH_NOT_AVAIL 15 /**< Health value not available */

/**@brief Glucose measurement context medication ID */
#define BLE_GLS_CONTEXT_MED_RAPID 1    /**< Rapid acting insulin */
#define BLE_GLS_CONTEXT_MED_SHORT 2    /**< Short acting insulin */
#define BLE_GLS_CONTEXT_MED_INTERMED 3 /**< Intermediate acting insulin */
#define BLE_GLS_CONTEXT_MED_LONG 4     /**< Long acting insulin */
#define BLE_GLS_CONTEXT_MED_PREMIX 5   /**< Pre-mixed insulin */

/**@brief SFLOAT format (IEEE-11073 16-bit FLOAT, meaning 4 bits for exponent (base 10) and 12 bits mantissa) */
typedef struct
{
    int8_t exponent;  /**< Base 10 exponent, should be using only 4 bits */
    int16_t mantissa; /**< Mantissa, should be using only 12 bits */
} sfloat_t;

/**@brief Glucose Service event type. */
typedef enum
{
    BLE_GLS_EVT_NOTIFICATION_ENABLED, /**< Glucose value notification enabled event. */
    BLE_GLS_EVT_NOTIFICATION_DISABLED /**< Glucose value notification disabled event. */
} ble_gls_evt_type_t;

/**@brief Glucose Service event. */
typedef struct
{
    ble_gls_evt_type_t evt_type; /**< Type of event. */
} ble_gls_evt_t;

// Forward declaration of the ble_gls_t type.
typedef struct ble_gls_s ble_gls_t;

/**@brief Glucose Service event handler type. */
typedef void (*ble_gls_evt_handler_t)(ble_gls_t *p_gls, ble_gls_evt_t *p_evt);

/**@brief Glucose Measurement structure. This contains glucose measurement value. */
typedef struct
{
    uint8_t flags;                       /**< Flags */
    uint16_t sequence_number;            /**< Sequence number */
    ble_date_time_t base_time;           /**< Time stamp */
    int16_t time_offset;                 /**< Time offset */
    sfloat_t glucose_concentration;      /**< Glucose concentration */
    uint8_t type;                        /**< Type */
    uint8_t sample_location;             /**< Sample location */
    uint16_t sensor_status_annunciation; /**< Sensor status annunciation */
} ble_gls_meas_t;

/**@brief Glucose measurement context structure */
typedef struct
{
    uint8_t flags;              /**< Flags */
    uint8_t extended_flags;     /**< Extended Flags */
    uint8_t carbohydrate_id;    /**< Carbohydrate ID */
    sfloat_t carbohydrate;      /**< Carbohydrate */
    uint8_t meal;               /**< Meal */
    uint8_t tester_and_health;  /**< Tester and health */
    uint16_t exercise_duration; /**< Exercise Duration */
    uint8_t exercise_intensity; /**< Exercise Intensity */
    uint8_t medication_id;      /**< Medication ID */
    sfloat_t medication;        /**< Medication */
    uint16_t hba1c;             /**< HbA1c */
} ble_gls_meas_context_t;

/**@brief Glucose measurement record */
typedef struct
{
    ble_gls_meas_t meas;            /**< Glucose measurement */
    ble_gls_meas_context_t context; /**< Glucose measurement context */
} ble_gls_rec_t;

/**@brief Glucose Service init structure. This contains all options and data needed for
 *        initialization of the service. */
typedef struct
{
    ble_gls_evt_handler_t evt_handler;     /**< Event handler to be called for handling events in the Glucose Service. */
    ble_srv_error_handler_t error_handler; /**< Function to be called in case of an error. */
    uint16_t feature;                      /**< Glucose Feature value indicating supported features. */
    bool is_context_supported;             /**< Determines if optional Glucose Measurement Context is to be supported. */
} ble_gls_init_t;

/**@brief Glucose Service structure. This contains various status information for the service. */
struct ble_gls_s
{
    ble_gls_evt_handler_t evt_handler;            /**< Event handler to be called for handling events in the Glucose Service. */
    ble_srv_error_handler_t error_handler;        /**< Function to be called in case of an error. */
    uint16_t service_handle;                      /**< Handle of Glucose Service (as provided by the BLE stack). */
    ble_gatts_char_handles_t glm_handles;         /**< Handles related to the Glucose Measurement characteristic. */
    ble_gatts_char_handles_t glm_context_handles; /**< Handles related to the Glucose Measurement Context characteristic. */
    ble_gatts_char_handles_t glf_handles;         /**< Handles related to the Glucose Feature characteristic. */
    ble_gatts_char_handles_t racp_handles;        /**< Handles related to the Record Access Control Point characteristic. */
    uint16_t conn_handle;                         /**< Handle of the current connection (as provided by the BLE stack, is BLE_CONN_HANDLE_INVALID if not in a connection). */
    uint16_t feature;
    bool is_context_supported;
};

/**@brief Function for initializing the Glucose Service.
 *
 * @details This call allows the application to initialize the Glucose Service.
 *
 * @param[out]  p_gls       Glucose Service structure. This structure will have to be supplied by
 *                          the application. It will be initialized by this function, and will later
 *                          be used to identify this particular service instance.
 * @param[in]   p_gls_init  Information needed to initialize the service.
 *
 * @return      NRF_SUCCESS on successful initialization of service, otherwise an error code.
 */
uint32_t ble_gls_init(ble_gls_t *p_gls, const ble_gls_init_t *p_gls_init);

/**@brief Function for handling the Application's BLE Stack events.
 *
 * @details Handles all events from the BLE stack of interest to the Glucose Service.
 *
 * @param[in]   p_gls      Glucose Service structure.
 * @param[in]   p_ble_evt  Event received from the BLE stack.
 */
void ble_gls_on_ble_evt(ble_gls_t *p_gls, ble_evt_t *p_ble_evt);

/**@brief Function for reporting a new glucose measurement to the glucose service module.
 *
 * @details The application calls this function after having performed a new glucose measurement.
 *          The new measurement is recorded in the RACP database.
 *
 * @param[in]   p_gls                    Glucose Service structure.
 * @param[in]   p_rec                    Pointer to glucose record (measurement plus context).
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
uint32_t ble_gls_glucose_new_meas(ble_gls_t *p_gls, ble_gls_rec_t *p_rec);

#endif // BLE_GLS_H__

/** @} */
